package com.bsj.travel.monitor.task;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bsj.travel.cached.redis.RedisCached;
import com.bsj.travel.constants.RedisConstant;
import com.bsj.travel.def.common.DO.ProductDO;
import com.bsj.travel.mapper.mysql.ProductMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Instant;
import java.time.ZoneId;
import java.util.*;

/**
 * @author yinhao
 * @version 1.0
 * @description 定时任务调度方法
 * @date 2024/1/24
 */
@Service("tcTask")
@Slf4j
public class TcTask {

    /**
     * mqtt 服务端节点
     */
    private static final String SERVER_NODES = "mqtt:server:nodes:";
    /**
     * 连接状态存储
     */
    private static final String CONNECT_STATUS = "mqtt:connect:status:";

    @Resource
    private ProductMapper productMapper;

    @Autowired
    private RedisCached redisCached;

    public void tcParams(String params) {
        log.info("TcTask 执行有参方法： {}", params);
    }

    public void tcNoParams() {
        log.info("TcTask 执行无参方法");
    }

    /**
     * 统计当前分钟的客户端在线数量
     */
    public void onlineClientSize() {
        //key 为产品key， value为当前在线设备数
        Map<String, Long> productMap = new HashMap<>();
        //当前分钟的时间戳(整分钟)
        String timestamp = Instant.now().atZone(ZoneId.systemDefault()).withSecond(0).withNano(0).toInstant().toEpochMilli() + "";
        Map<String, String> map = redisCached.hgetAll(SERVER_NODES);
        if (!map.isEmpty()) {
            Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, String> entry = iterator.next();
                String key = entry.getKey();
                //单个节点的总在线数
                Map<String, String> all = redisCached.hgetAll(CONNECT_STATUS + key);
                //然后按照产品进行分类
                Iterator<Map.Entry<String, String>> allIter = all.entrySet().iterator();
                while (allIter.hasNext()) {
                    Map.Entry<String, String> allNext = allIter.next();
                    String allNextKey = allNext.getKey();
                    String[] split = allNextKey.split("&");
                    String productKey = split[1];
                    Long sum = productMap.get(productKey);
                    if (sum == null) {
                        //初始化为1
                        productMap.put(productKey, 1L);
                    } else {
                        sum += 1;
                        productMap.put(productKey, sum);
                    }
                }
            }
        }
        Iterator<Map.Entry<String, Long>> entryIterator = productMap.entrySet().iterator();
        while (entryIterator.hasNext()) {
            Map.Entry<String, Long> longEntry = entryIterator.next();
            //产品key
            String key = longEntry.getKey();
            //当前在线数
            Long value = longEntry.getValue();
            //按照每个产品的分类写入当前时间点的在线数
            redisCached.hset(RedisConstant.CLIENT_CONNECT_SUM_KEY + key, timestamp, value + "");
        }
    }

    /**
     * 统计清除当前分钟的客户端在线数量旧数据
     */
    public void cleanOldOnlineClientSize() {
        // 3天前数据
        long threeDaysAgo = System.currentTimeMillis() - (3 * 24 * 60 * 60 * 1000);
        List<ProductDO> productList = productMapper.selectList(new QueryWrapper<ProductDO>().select("productKey"));
        if (CollectionUtil.isNotEmpty(productList)) {
            productList.forEach(v -> {
                String hashKey = RedisConstant.CLIENT_CONNECT_SUM_KEY + v.getProductKey();
                // 获取所有字段名
                Set<String> keys = redisCached.hkeys(hashKey);
                for (String key : keys) {
                    long fileId = Long.parseLong(key);
                    if (fileId < threeDaysAgo) {
                        // 删除过期字段
                        redisCached.hdel(hashKey, key);
                    }
                }
            });
        }
    }
}
